package com.srtp.secureprotocol

import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import com.srtp.secureprotocol.controller.InitializeController
import com.srtp.secureprotocol.controller.KeyMangeController
import com.srtp.secureprotocol.controller.SessionController
import com.srtp.secureprotocol.main.SecureProtocol
import com.srtp.secureprotocol.serializable.req.CreatePasswordHashRequest
import com.srtp.secureprotocol.serializable.req.CreateSessionRequest
import com.srtp.secureprotocol.serializable.req.DecryptTextRequest
import com.srtp.secureprotocol.serializable.req.EncryptTextRequest
import com.srtp.secureprotocol.serializable.req.GeneratePreKeysRequest
import com.srtp.secureprotocol.serializable.req.InitStickySessionRequest
import com.srtp.secureprotocol.serializable.req.InitializeRequest
import com.srtp.secureprotocol.serializable.req.PreKeysRequest
import com.srtp.secureprotocol.serializable.req.ReInitializedRequest
import com.srtp.secureprotocol.serializable.req.SenderKeyRequest
import com.srtp.secureprotocol.serializable.req.SessionBundle
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.server.netty.NettyApplicationEngine
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.post
import io.ktor.server.routing.routing

class SecureProtocolHttpServer(
    private val context: Context,
    private val port: Int = 8088
) {
    private val secureProtocol = SecureProtocol(context, "com.srtp.secureprotocol")
    private var server: NettyApplicationEngine? = null

    @SuppressLint("LongLogTag")
    fun start() {
        try {
            server = embeddedServer(Netty, port = port, host = "0.0.0.0") {
                install(ContentNegotiation) {
                    json()
                }

                routing {

                    post("/api/secure/init") {
                        val request = call.receive<InitializeRequest>()
                        val response = InitializeController().handleInitialize(
                            request.userId,
                            request.password,
                            secureProtocol
                        )
                        call.respond(response)
                    }

                    post("/api/secure/reinit") {
                        val request = call.receive<ReInitializedRequest>()
                        InitializeController().reInitialized(
                            request.bundle,
                            request.userId,
                            request.password,
                            secureProtocol,
                            call
                        )
                    }

                    post("/secure/decryptPreKeys") {
                        val request = call.receive<PreKeysRequest>()
                        InitializeController().decryptPreKeys(
                            request.preKeys,
                            secureProtocol,
                            call
                        )
                    }

                    post("/secure/createPasswordHash") {
                        val request = call.receive<CreatePasswordHashRequest>()
                        val response = InitializeController().createPasswordHashRequest(
                            request.password,
                            request.salt,
                            secureProtocol
                        )
                        call.respond(response)
                    }

                    post("/secure/createNewPasswordHash") {
                        val request = call.receive<String>()
                        InitializeController().createNewPasswordHash(
                            request,
                            secureProtocol,
                            call
                        )
                    }

                    post("api/secure/initPairwiseSession") {
                        val request = call.receive<SessionBundle>()
                        SessionController().initPairwiseSession(
                            request,
                            secureProtocol,
                            call
                        )
                    }

                    post("/secure/encryptTextPairwise") {
                        SessionController().encryptTextPairwise(secureProtocol, call)
                    }

                    post("/secure/decryptTextPairwise") {
                        SessionController().decryptTextPairwise(secureProtocol, call)
                    }

                    post("api/secure/createStickySession") {
                        val request = call.receive<CreateSessionRequest>()
                        SessionController().createStickySession(request, secureProtocol, call)
                    }

                    post("api/secure/getSenderKey") {
                        val request = call.receive<SenderKeyRequest>()
                        SessionController().getSenderKey(request, secureProtocol, call)
                    }

                    post("api/secure/initStickySession") {
                        val request = call.receive<InitStickySessionRequest>()
                        SessionController().initStickySession(request, secureProtocol, call)
                    }

                    post("api/secure/encryptText") {
                        val request = call.receive<EncryptTextRequest>()
                        SessionController().encryptText(request, secureProtocol, call)
                    }
                    post("api/secure/decryptText") {
                        val request = call.receive<DecryptTextRequest>()
                        SessionController().decryptText(request, secureProtocol, call)
                    }

                    post("/secure/sessionExists") {
                        SessionController().sessionExists(secureProtocol, call)
                    }
                    post("/secure/getChainStep") {
                        SessionController().getChainStep(secureProtocol, call)
                    }

                    post("/secure/ratchetChain") {
                        SessionController().ratchetChain(secureProtocol, call)
                    }

                    post("/secure/reinitMyStickySession") {
                        SessionController().reinitMyStickySession(secureProtocol, call)
                    }

                    post("/secure/decryptStickyKey") {
                        SessionController().decryptStickyKey(secureProtocol, call)
                    }

                    post("/secure/swapIdentityKey") {
                        SessionController().swapIdentityKey(secureProtocol, call)
                    }

                    post("/secure/decryptFile") {
                        SessionController().decryptFile(secureProtocol, call)
                    }

                    post("/secure/encryptFile") {
                        SessionController().encryptFile(secureProtocol, call)
                    }

                    post("/secure/refreshIdentityKey") {
                        KeyMangeController().refreshIdentityKey(secureProtocol, call)
                    }

                    post("/secure/refreshSignedPreKey") {
                        KeyMangeController().refreshSignedPreKey(secureProtocol, call)
                    }

                    post("/api/secure/generatePreKeys") {
                        val request = call.receive<GeneratePreKeysRequest>()
                        KeyMangeController().generatePreKeys(request, secureProtocol, call)
                    }

                    post("/secure/reEncryptKeys") {
                        KeyMangeController().reEncryptKeys(secureProtocol, call)
                    }

                }


            }.start(wait = false)

            Log.i("SecureProtocolHttpServer", "HTTP Server started on port $port")
        } catch (e: Exception) {
            Log.e("SecureProtocolHttpServer", "Failed to start server", e)
        }
    }

    @SuppressLint("LongLogTag")
    fun stop() {
        try {
            server?.stop(1000, 2000)
            Log.i("SecureProtocolHttpServer", "HTTP server stopped")
        } catch (e: Exception) {
            Log.e("SecureProtocolHttpServer", "Error stopping server", e)
        }
    }
}